package com.dexgdx.game.manager;

import java.util.ArrayList;
import java.util.List;

import com.dexgdx.game.factory.ActorFactory;
import com.dexgdx.game.json.JSONActor;
import com.dexgdx.game.json.JSONManager;
import com.dexgdx.game.structure.actor.AbstractActor;
import com.dexgdx.game.structure.actor.EnemyActor;
import com.dexgdx.game.structure.actor.PlayerActor;
import com.dexgdx.game.structure.base.BaseObject;
import com.dexgdx.game.structure.base.BaseRegion;
import com.dexgdx.game.structure.base.MobileObject;

public class GameData {

	List<BaseObject> baseObjectList ;
	
	List<BaseObject> nonActorObjectList ;
	List<EnemyActor> enemyList ;
	List<PlayerActor> playerList ;
	List<PlayerActor> selectedPlayerList;

	List<MobileObject> movingObjects;
	List<AbstractActor> attackingActors;
	

	public GameData() {
		super();
		this.baseObjectList = new ArrayList<BaseObject>();
		
		this.nonActorObjectList = new ArrayList<BaseObject>();
		this.enemyList = new ArrayList<EnemyActor>();
		this.playerList = new ArrayList<PlayerActor>();
		this.selectedPlayerList = new ArrayList<PlayerActor>();
		
		this.movingObjects = new ArrayList<MobileObject>();
		this.attackingActors = new ArrayList<AbstractActor>();
	}

	public void addNonActorObject(BaseObject baseObject){
		baseObjectList.add(baseObject);
		nonActorObjectList.add(baseObject);
	}

	public void removeNonActorObject(BaseObject baseObject){
		baseObjectList.remove(baseObject);
		nonActorObjectList.remove(baseObject);
	}
	
	public void loadActorsFromJSON(){
		JSONManager.saveJSONActor();
		ArrayList<JSONActor> jSONActors = JSONManager.getJSONActor();
		for (JSONActor jsonActor : jSONActors) {
			addActor(ActorFactory.loadFromJSONActor(jsonActor));
		}
	}
	
	public void addActor(AbstractActor actor){
		baseObjectList.add(actor);
		if(actor instanceof PlayerActor)
			playerList.add((PlayerActor)actor);
		else if(actor instanceof EnemyActor)
			enemyList.add((EnemyActor)actor);
	}
	
	public void removeActor(AbstractActor actor){
		enemyList.remove(actor);
		playerList.remove(actor);
		if(actor instanceof PlayerActor)
			deSelectPlayer((PlayerActor)actor);
	}
	
	public AbstractActor getActor(int actorIndex){
		return (AbstractActor)baseObjectList.get(actorIndex);
	}

	public void selectPlayer(PlayerActor player, boolean multiple){
		if(!multiple){
			deSelectAllPlayers();
		}
		if(playerList.contains(player) && !selectedPlayerList.contains(player)){
			player.setSelected(true);
			selectedPlayerList.add(player);
		}
	}
	
	public void deSelectPlayer(PlayerActor player){
		player.setSelected(false);
		selectedPlayerList.remove(player);
	}

	public void selectSinglePlayer(PlayerActor player){
		selectPlayer(player, false);
	}
	
	public void selectAllPlayers(){
		for (PlayerActor player : playerList) {
			selectPlayer(player, true);
		}
	}
	
	public void deSelectAllPlayers(){
		Object[] playerToDeselect = selectedPlayerList.toArray();
		for (Object player : playerToDeselect) {
			deSelectPlayer((PlayerActor)player);
		}
	}
	
	public boolean isActorSelected(AbstractActor actor){
		return selectedPlayerList.contains(actor);
	}
	
	public boolean isAnyPlayerSelected(){
		return selectedPlayerList.size() > 0;
	}

	
	public void addMovingObject(MobileObject movingObject){
		if(!movingObjects.contains(movingObject)){
			movingObjects.add(movingObject);
			if(!(movingObject instanceof AbstractActor)){
				nonActorObjectList.add(movingObject);
			}
			if(!baseObjectList.contains(movingObject)){
				baseObjectList.add(movingObject);
			}
		}
	}
	
	public void removeMovingObject(MobileObject movingObject){
		movingObjects.remove(movingObject);
		if(!(movingObject instanceof AbstractActor)){
			nonActorObjectList.remove(movingObject);
			baseObjectList.remove(movingObject);
		}
	}
	
	public void addAttackingActor(AbstractActor attackingActor, AbstractActor targetActor){
		attackingActor.startAttacking(targetActor);
		if(!attackingActors.contains(attackingActor)){
			attackingActors.add(attackingActor);
		}
	}
	
	public void removeAttackingActor(AbstractActor attackingActor){
		attackingActor.stopAttacking();
		attackingActors.remove(attackingActor);
	}
	
	public List<EnemyActor> getEnemyList() {
		return enemyList;
	}
	public List<PlayerActor> getPlayerList() {
		return playerList;
	}
	public List<PlayerActor> getSelectedPlayerList() {
		return selectedPlayerList;
	}
	public List<MobileObject> getMovingObjects() {
		return movingObjects;
	}
	public List<AbstractActor> getAttackingActors() {
		return attackingActors;
	}

	public List<BaseObject> getBaseObjectList() {
		return baseObjectList;
	}

	public List<BaseObject> getNonActorObjectList() {
		return nonActorObjectList;
	}

	public synchronized BaseObject getCollidingObject(BaseObject exclude, BaseRegion baseRegion) {
		BaseObject response = null;
		boolean isFound = false, isColliding = false, isSelf = false;
		
		for (BaseObject baseObject : enemyList){
			if(baseObject != exclude){
				isColliding = baseObject.isCollidingWith(baseRegion);
				if(isColliding){
					response = baseObject;
					isFound = true;
					break;
				}
			}
			else {
				isSelf = true;
				break;
			}
		}
		if(!isFound || !isSelf){
			for (BaseObject baseObject : playerList){
				if(baseObject != exclude){
					isColliding = baseObject.isCollidingWith(baseRegion);
					if(isColliding){
						response = baseObject;
						isFound = true;
						break;
					}
				}
			}
		}
		return response;
	}
}
